package main

import (
	base "2024-fall-etohlcin3-backend/cmd/kitex_gen/industics/blockchain/base"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"github.com/hyperledger/fabric-gateway/pkg/client"
)

// LabelServiceImpl implements the last service interface defined in the IDL.
type LabelServiceImpl struct{}

var LabelOrg *client.Contract

type LabelInformationIDs struct {
	SaleContractID string `json:"saleContractID"`
	SaleOrderID    string `json:"saleOrderID"`
	SaleDeliveryID string `json:"saleDeliveryID"`
	SaleReturnID   string `json:"saleReturnID"`

	ProjectMilestoneID string `json:"projectMilestoneID"`
	ProjectDocHashID   string `json:"projectDocHashID"`
	DesignBOMID        string `json:"designBOMID"`
	DesignECNID        string `json:"designECNID"`

	ProductionPlanID       string `json:"productionPlanID"`
	ProductionPlanReportID string `json:"productionPlanReportID"`

	ProductionWorkOrderID  string `json:"productionWorkOrderID"`
	ProductionLotTracingID string `json:"productionLotTracingID"`
	ProductionESOPID       string `json:"productionESOPID"`

	WarehouseOutboundID string `json:"warehouseOutboundID"`
	WarehouseMaterialID string `json:"warehouseMaterialID"`

	PurchaseRequireID   string `json:"purchaseRequireID"`
	PurchaseOrderID     string `json:"purchaseOrderID"`
	PurchaseContractID  string `json:"purchaseContractID"`
	QualityInspectionID string `json:"qualityInspectionID"`
}

// GetPublicInfo implements the LabelServiceImpl interface.
func (s *LabelServiceImpl) GetPublicInfo(ctx context.Context, req *base.BaseGetReq) (resp *base.BaseGetResp, err error) {
	evaluateResult, err := readForKey(req.GetId())
	if err != nil {
		return nil, err
	}
	var infoIDs LabelInformationIDs
	err = json.Unmarshal(evaluateResult, &infoIDs)
	if err != nil {
		return nil, err
	}

	var publicInfos = make(map[string]string)

	// resStr, err := getSaleContract(infoIDs.SaleContractID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["saleContract"] = resStr

	// resStr, err = getSaleOrder(infoIDs.SaleOrderID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["saleOrder"] = resStr

	// resStr, err = getSaleDelivery(infoIDs.SaleDeliveryID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["saleDelivery"] = resStr

	// resStr, err = getSaleReturn(infoIDs.SaleReturnID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["saleReturn"] = resStr

	resStr, err := getProjectMilestone(infoIDs.ProjectMilestoneID)
	if err != nil {
		return nil, err
	}
	publicInfos["projectMilestone"] = resStr

	resStr, err = getProjectDocHash(infoIDs.ProjectDocHashID)
	if err != nil {
		return nil, err
	}
	publicInfos["projectDocHash"] = resStr

	resStr, err = getDesignBOM(infoIDs.DesignBOMID)
	if err != nil {
		return nil, err
	}
	publicInfos["designBOM"] = resStr

	resStr, err = getDesignECN(infoIDs.DesignECNID)
	if err != nil {
		return nil, err
	}
	publicInfos["designECN"] = resStr

	// resStr, err = getProductionPlan(infoIDs.ProductionPlanID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["productionPlan"] = resStr

	// resStr, err = getProductionPlanReport(infoIDs.ProductionPlanReportID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["productionPlanReport"] = resStr

	resStr, err = getProductionWorkOrder(infoIDs.ProductionWorkOrderID)
	if err != nil {
		return nil, err
	}
	publicInfos["productionWorkOrder"] = resStr

	resStr, err = getProductionLotTracing(infoIDs.ProductionLotTracingID)
	if err != nil {
		return nil, err
	}
	publicInfos["productionLotTracing"] = resStr

	resStr, err = getProductionESOP(infoIDs.ProductionESOPID)
	if err != nil {
		return nil, err
	}
	publicInfos["productionESOP"] = resStr

	// resStr, err = getWarehouseOutbound(infoIDs.WarehouseOutboundID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["warehouseOutbound"] = resStr

	// resStr, err = getWarehouseMaterial(infoIDs.WarehouseMaterialID)
	// if err != nil {
	// 	return nil, err
	// }
	// allInfos["warehouseMaterial"] = resStr

	resStr, err = getPurchaseRequire(infoIDs.PurchaseRequireID)
	if err != nil {
		return nil, err
	}
	publicInfos["purchaseRequire"] = resStr

	resStr, err = getPurchaseOrder(infoIDs.PurchaseOrderID)
	if err != nil {
		return nil, err
	}
	publicInfos["purchaseOrder"] = resStr

	resStr, err = getPurchaseContract(infoIDs.PurchaseContractID)
	if err != nil {
		return nil, err
	}
	publicInfos["purchaseContract"] = resStr

	resStr, err = getQualityInspection(infoIDs.QualityInspectionID)
	if err != nil {
		return nil, err
	}
	publicInfos["qualityInspection"] = resStr

	infoJson, err := json.Marshal(publicInfos)

	resp = &base.BaseGetResp{
		Code:     "200",
		Msg:      "ok",
		JsonData: string(infoJson),
	}
	return
}

// GetAllInfo implements the LabelServiceImpl interface.
func (s *LabelServiceImpl) GetAllInfo(ctx context.Context, req *base.BaseGetReq) (resp *base.BaseGetResp, err error) {
	evaluateResult, err := readForKey(req.GetId())
	if err != nil {
		return nil, err
	}
	var infoIDs LabelInformationIDs
	err = json.Unmarshal(evaluateResult, &infoIDs)
	if err != nil {
		return nil, err
	}

	var allInfos = make(map[string]string)

	resStr, err := getSaleContract(infoIDs.SaleContractID)
	if err != nil {
		return nil, err
	}
	allInfos["saleContract"] = resStr

	resStr, err = getSaleOrder(infoIDs.SaleOrderID)
	if err != nil {
		return nil, err
	}
	allInfos["saleOrder"] = resStr

	resStr, err = getSaleDelivery(infoIDs.SaleDeliveryID)
	if err != nil {
		return nil, err
	}
	allInfos["saleDelivery"] = resStr

	resStr, err = getSaleReturn(infoIDs.SaleReturnID)
	if err != nil {
		return nil, err
	}
	allInfos["saleReturn"] = resStr

	resStr, err = getProjectMilestone(infoIDs.ProjectMilestoneID)
	if err != nil {
		return nil, err
	}
	allInfos["projectMilestone"] = resStr

	resStr, err = getProjectDocHash(infoIDs.ProjectDocHashID)
	if err != nil {
		return nil, err
	}
	allInfos["projectDocHash"] = resStr

	resStr, err = getDesignBOM(infoIDs.DesignBOMID)
	if err != nil {
		return nil, err
	}
	allInfos["designBOM"] = resStr

	resStr, err = getDesignECN(infoIDs.DesignECNID)
	if err != nil {
		return nil, err
	}
	allInfos["designECN"] = resStr

	resStr, err = getProductionPlan(infoIDs.ProductionPlanID)
	if err != nil {
		return nil, err
	}
	allInfos["productionPlan"] = resStr

	resStr, err = getProductionPlanReport(infoIDs.ProductionPlanReportID)
	if err != nil {
		return nil, err
	}
	allInfos["productionPlanReport"] = resStr

	resStr, err = getProductionWorkOrder(infoIDs.ProductionWorkOrderID)
	if err != nil {
		return nil, err
	}
	allInfos["productionWorkOrder"] = resStr

	resStr, err = getProductionLotTracing(infoIDs.ProductionLotTracingID)
	if err != nil {
		return nil, err
	}
	allInfos["productionLotTracing"] = resStr

	resStr, err = getProductionESOP(infoIDs.ProductionESOPID)
	if err != nil {
		return nil, err
	}
	allInfos["productionESOP"] = resStr

	resStr, err = getWarehouseOutbound(infoIDs.WarehouseOutboundID)
	if err != nil {
		return nil, err
	}
	allInfos["warehouseOutbound"] = resStr

	resStr, err = getWarehouseMaterial(infoIDs.WarehouseMaterialID)
	if err != nil {
		return nil, err
	}
	allInfos["warehouseMaterial"] = resStr

	resStr, err = getPurchaseRequire(infoIDs.PurchaseRequireID)
	if err != nil {
		return nil, err
	}
	allInfos["purchaseRequire"] = resStr

	resStr, err = getPurchaseOrder(infoIDs.PurchaseOrderID)
	if err != nil {
		return nil, err
	}
	allInfos["purchaseOrder"] = resStr

	resStr, err = getPurchaseContract(infoIDs.PurchaseContractID)
	if err != nil {
		return nil, err
	}
	allInfos["purchaseContract"] = resStr

	resStr, err = getQualityInspection(infoIDs.QualityInspectionID)
	if err != nil {
		return nil, err
	}
	allInfos["qualityInspection"] = resStr

	infoJson, err := json.Marshal(allInfos)

	resp = &base.BaseGetResp{
		Code:     "200",
		Msg:      "ok",
		JsonData: string(infoJson),
	}
	return
}

// CreateSmartLabel implements the LabelServiceImpl interface.
func (s *LabelServiceImpl) CreateSmartLabel(ctx context.Context, req *base.BasePostReq) (resp *base.BasePostResp, err error) {
	_, err = createForKey(req.GetId(), req.JsonData)
	if err != nil {
		return nil, err
	}
	resp = &base.BasePostResp{
		Code: "201",
		Msg:  "ok",
	}
	return
}

// UpdateSmartLabel implements the LabelServiceImpl interface.
func (s *LabelServiceImpl) UpdateSmartLabel(ctx context.Context, req *base.BasePutReq) (resp *base.BasePutResp, err error) {
	_, err = updateForKey(req.GetId(), req.JsonData)
	if err != nil {
		return nil, err
	}
	resp = &base.BasePutResp{
		Code: "200",
		Msg:  "ok",
	}
	return
}

// DeleteSmartLabel implements the LabelServiceImpl interface.
func (s *LabelServiceImpl) DeleteSmartLabel(ctx context.Context, req *base.BaseDeleteReq) (resp *base.BaseDeleteResp, err error) {
	_, err = deleteForKey(req.GetId())
	if err != nil {
		return nil, err
	}
	resp = &base.BaseDeleteResp{
		Code: "200",
		Msg:  "ok",
	}
	return
}
func readForKey(formID string) ([]byte, error) {
	return LabelOrg.EvaluateTransaction("ReadForm", formID)
}
func createForKey(formID string, formJSON string) ([]byte, error) {
	return LabelOrg.SubmitTransaction("CreateForm", formID, formJSON)
}
func updateForKey(formID string, formJSON string) ([]byte, error) {
	return LabelOrg.SubmitTransaction("UpdateForm", formID, formJSON)
}
func deleteForKey(formID string) ([]byte, error) {
	return LabelOrg.SubmitTransaction("DeleteForm", formID)
}

func extractJSON(response *http.Response) (string, error) {
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		fmt.Println("Error reading response body:", err)
		return "failed to read http body", err
	}
	var result map[string]string
	err = json.Unmarshal(body, &result)
	if err != nil {
		fmt.Println("Error parsing JSON:", err)
		return "failed to parse json", err
	}
	return result["jsonData"], nil
}

func getSaleContract(saleContractID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/sale/GetSaleContract?id=" + saleContractID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getSaleOrder(saleOrderID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/sale/GetSaleOrder?id=" + saleOrderID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getSaleDelivery(saleDeliveryID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/sale/GetSaleDelivery?id=" + saleDeliveryID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getSaleReturn(saleReturnID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/sale/GetSaleReturn?id=" + saleReturnID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProjectMilestone(projectMilestoneID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/project/GetMileStone?id=" + projectMilestoneID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProjectDocHash(projectDocHashID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/project/GetProjectDocHash?id=" + projectDocHashID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getDesignBOM(designBOMID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/design/GetBOM?id=" + designBOMID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getDesignECN(designECNID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/design/GetECN?id=" + designECNID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProductionPlan(productionPlanID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/plan/GetProductionPlan?id=" + productionPlanID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProductionPlanReport(productionPlanReportID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/plan/GetProductionPlanReport?id=" + productionPlanReportID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProductionWorkOrder(productionWorkOrderID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/production/GetWorkOrder?id=" + productionWorkOrderID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProductionLotTracing(productionLotTracingID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/production/GetLotTracing?id=" + productionLotTracingID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getProductionESOP(productionESOPID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/production/GetESOP?id=" + productionESOPID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getWarehouseOutbound(warehouseOutboundID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/warehouse/GetWarehouseOutbound?id=" + warehouseOutboundID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getWarehouseMaterial(warehouseMaterialID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/warehouse/GetWarehouseOutbound?id=" + warehouseMaterialID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getPurchaseRequire(purchaseRequireID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/purchase/GetPurchaseRequire?id=" + purchaseRequireID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getPurchaseOrder(purchaseOrderID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/purchase/GetPurchaseOrder?id=" + purchaseOrderID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getPurchaseContract(purchaseContractID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/purchase/GetPurchaseContract?id=" + purchaseContractID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}

func getQualityInspection(qualityInspectionID string) (string, error) {
	response, err := http.Get("http://apigateway:80/api/quality/GetQualityInspection?id=" + qualityInspectionID)
	if err != nil {
		fmt.Println("Error:", err)
		return "failed to get from ledger", err
	}
	return extractJSON(response)
}
